package com.seed.menudesign.service.impl;

import com.seed.core.pojo.dto.SeedMessageDTO;
import com.seed.menudesign.entity.MenuEntity;
import com.seed.menudesign.service.MenuDesignService;
import lombok.extern.slf4j.Slf4j;
import org.commonmark.Extension;
import org.commonmark.ext.gfm.tables.TablesExtension;
import org.commonmark.node.Node;
import org.commonmark.parser.Parser;
import org.commonmark.renderer.html.HtmlRenderer;
import org.jeecg.modules.system.entity.SysPermission;
import org.jeecg.modules.system.service.ISysPermissionService;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @author gchiaway
 * 日期: 2021-01-14
 * 时间: 14:28
 */
@Slf4j
@Service("menuDesignService")
public class MenuDesignServiceImpl implements MenuDesignService {

    @Autowired
    private ISysPermissionService sysPermissionService;

    /**
     * 导入markdown格式的菜单文档
     *
     * @param inFilePath 导入路径
     * @return 是否成功
     */
    @Override
    public Boolean importMenu(String inFilePath) {
        Document doc = this.getDocument(inFilePath);
        if (StringUtils.isEmpty(doc)) {
            return false;
        }
        List<MenuEntity> menuEntityList = this.readerMenuEntity(1, doc.body());
        if (CollectionUtils.isEmpty(menuEntityList)) {
            return false;
        }
        SeedMessageDTO saveDTO = this.saveMenuRecursion(null, menuEntityList);
        return saveDTO.getSuccess();
    }

    /**
     * 根据HTML对象解析菜单结构
     *
     * @param level    层级数,从一开始
     * @param document HTML对象
     * @return 菜单结构
     */
    private List<MenuEntity> readerMenuEntity(int level, Element document) {
        List<MenuEntity> menuEntityList = new ArrayList<>();
        if (StringUtils.isEmpty(document.text())) {
            return null;
        }
        Elements firstLevelMenuList = document.getElementsByTag("h" + level);
        String startElements = "<h" + level + ">";
        String endElements = "</h" + level + ">";
        for (int i = 0; i < firstLevelMenuList.size(); i++) {
            Element firstLevelMenu = firstLevelMenuList.get(i);
            if (StringUtils.isEmpty(firstLevelMenu.text())) {
                continue;
            }
            String firstLevelMenuString = firstLevelMenu.text().replaceAll(" ", "");
            String name;
            String url;
            if (firstLevelMenuString.contains("(")) {
                name = firstLevelMenuString.split("[(]", 2)[0];
                url = firstLevelMenuString.split("[(]", 2)[1].replace(")", "");
            } else {
                name = firstLevelMenuString;
                url = "";
            }
            MenuEntity menuEntity = new MenuEntity();
            if (level == 1) {
                menuEntity.setMenuType(0);
            } else {
                menuEntity.setMenuType(1);
            }
            menuEntity.setSortNo((double) (i + 1));
            if (name.contains(",")) {
                menuEntity.setIcon(name.split(",")[0]);
                menuEntity.setName(name.split(",")[1]);
            } else {
                menuEntity.setIcon("edit");
                menuEntity.setName(name);
            }
            if (!StringUtils.isEmpty(url)) {
                if (url.startsWith("/")) {
                    menuEntity.setUrl(url);
                    menuEntity.setComponentName(url.replaceFirst("/", ""));
                } else {
                    menuEntity.setUrl("/" + url);
                    menuEntity.setComponentName(url);
                }
            } else {
                menuEntity.setUrl("");
                menuEntity.setComponentName("layouts/RouteView");
            }
            Element childDocument;
            String documentHtml = document.html().replace("<body>", "").replace("</body>", "");
            String firstLevelMenuHtmlString = startElements + firstLevelMenu.text() + endElements;
            if (i == (firstLevelMenuList.size() - 1)) {
                String[] childDocumentHtml = documentHtml.split(firstLevelMenuHtmlString);
                if (childDocumentHtml.length == 1) {
                    childDocument = Jsoup.parse(childDocumentHtml[0]).body();
                } else {
                    childDocument = Jsoup.parse(childDocumentHtml[1]).body();
                }
            } else {
                String secondLevelMenuHtmlString = startElements + firstLevelMenuList.get(i + 1).text() + endElements;
                String[] childDocumentHtml = documentHtml.split(firstLevelMenuHtmlString);
                if (childDocumentHtml.length == 1) {
                    childDocument = Jsoup.parse(childDocumentHtml[0]).body();
                } else {
                    childDocument = Jsoup.parse(childDocumentHtml[1].split(secondLevelMenuHtmlString)[0]).body();
                }
            }
            menuEntity.setChildMenu(this.readerMenuEntity(level + 1, childDocument));
            menuEntityList.add(menuEntity);
        }
        return menuEntityList;
    }

    /**
     * 保存菜单
     *
     * @param parentSysPermission 父级菜单
     * @param menuEntityList      菜单列表
     * @return
     */
    private SeedMessageDTO saveMenuRecursion(SysPermission parentSysPermission, List<MenuEntity> menuEntityList) {
        SeedMessageDTO result = new SeedMessageDTO();
        for (int i = 0; i < menuEntityList.size(); i++) {
            MenuEntity menuEntity = menuEntityList.get(i);
            SysPermission sysPermission = this.convertMenu(menuEntity);
            if (!StringUtils.isEmpty(sysPermission)) {
                if (!StringUtils.isEmpty(parentSysPermission)) {
                    sysPermission.setParentId(parentSysPermission.getId());
                }
                sysPermission.setSortNo((double) i);
                sysPermissionService.save(sysPermission);
                if (!CollectionUtils.isEmpty(menuEntity.getChildMenu())) {
                    saveMenuRecursion(sysPermission, menuEntity.getChildMenu());
                }
            }
        }
        return result;
    }

    private SysPermission convertMenu(MenuEntity parentMenu) {
        if (StringUtils.isEmpty(parentMenu)) {
            return null;
        }
        SysPermission sysPermission = new SysPermission();
        sysPermission.setName(parentMenu.getName());
        sysPermission.setPermsType("1");
        sysPermission.setIcon(parentMenu.getIcon());
        sysPermission.setUrl(parentMenu.getUrl());
        sysPermission.setComponent(parentMenu.getComponentName());
        sysPermission.setMenuType(parentMenu.getMenuType());
        sysPermission.setLeaf(true);
        sysPermission.setRoute(true);
        sysPermission.setKeepAlive(false);
        sysPermission.setRuleFlag(0);
        sysPermission.setHidden(false);
        sysPermission.setStatus("1");
        sysPermission.setAlwaysShow(false);
        sysPermission.setInternalOrExternal(false);
        return sysPermission;
    }

    /**
     * 用markdown文件转换为HTML文件
     *
     * @param markdownFilePath markdown文件路径
     * @return HTML文件
     */
    private Document getDocument(String markdownFilePath) {
        List<Extension> extensions = Arrays.asList(TablesExtension.create());
        Parser parser = Parser.builder()
                .extensions(extensions)
                .build();
        HtmlRenderer renderer = HtmlRenderer.builder()
                .extensions(extensions)
                .build();
        Node document;
        try (Reader reader = new FileReader(new File(markdownFilePath))) {
            document = parser.parseReader(reader);
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
        String html = renderer.render(document);
        return Jsoup.parseBodyFragment(html);
    }

    /**
     * 打印
     *
     * @param menuEntityList 菜单列表
     */
    private void printMenu(List<MenuEntity> menuEntityList) {
        for (MenuEntity menuEntity : menuEntityList) {
            System.out.println(menuEntity.getIcon() + "," + menuEntity.getName() + "(" + menuEntity.getComponentName() + ")");
            if (!StringUtils.isEmpty(menuEntity.getChildMenu())) {
                this.printMenu(menuEntity.getChildMenu());
            }
        }
    }


}
